home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / drawer.zip / SHAPE.PAS < prev    next >
Pascal/Delphi Source File  |  1993-01-04  |  15KB  |  709 lines

  1. {$L-,D-}
  2.  
  3. unit Shapes;
  4.  
  5. interface
  6.  
  7. const
  8.     HITTOLERANCE : word = 301;
  9.     HITPOINTTOLERANCE : word = 4;
  10.  
  11. type
  12.     ShapeTypes = ( sShape, sRectangle, sFRectangle, sEllipse, sFEllipse, sLine, sGText, sSelector);
  13.     Shape = object
  14.                 typ      : ShapeTypes;
  15.                 x, y     : word;        { position }
  16.                 xe, ye   : integer;        { extent }
  17.                 color    : word;        { color }
  18.                 selected : boolean;     { state of selection }
  19.                 procedure Error( s : string );
  20.                 procedure Initialize( x, y, xe, ye, color : word);
  21.                 function  Clone : shape;
  22.                 procedure Draw;
  23.                 procedure Erase;
  24.                 function  PtInRegion( px, py : word ) : boolean;
  25.                 procedure Select;
  26.                 procedure UnSelect;
  27.                 function  IsSelected : boolean;
  28.                 procedure Size( dx, dy : integer);
  29.                 procedure Move( dx, dy : word);
  30.                 procedure DrawHandles;
  31.                 function  OnHandle( px, py : word; var ax, ay : word) : boolean;
  32.                 procedure Save( var f : file );
  33.                 procedure Load( var f : file );
  34.             end;
  35.  
  36.     Rectangle = object(Shape)
  37.                     procedure Initialize(x, y, xe, ye, color : word); override;
  38.                     function  Clone : shape; override;
  39.                     procedure Load( var f : file ); override;
  40.                 end;
  41.  
  42.     FRectangle =    object(Rectangle)
  43.                         procedure Initialize(x, y, xe, ye, color : word); override;
  44.                         function  Clone : shape; override;
  45.                         procedure Load( var f : file ); override;
  46.                         procedure Draw; override;
  47.                         procedure Erase; override;
  48.                     end;
  49.  
  50.     Ellipse =     object(Shape)
  51.                     procedure Initialize(x, y, xe, ye, color : word); override;
  52.                     function  Clone : shape; override;
  53.                     procedure Load( var f : file ); override;
  54.                     procedure Draw; override;
  55.                     procedure Erase; override;
  56.                 end;
  57.  
  58.     FEllipse =     object(Ellipse)
  59.                     procedure Initialize(x, y, xe, ye, color : word); override;
  60.                     function  Clone : shape; override;
  61.                     procedure Load( var f : file ); override;
  62.                     procedure Draw; override;
  63.                     procedure Erase; override;
  64.                 end;
  65.  
  66.     Line =    object(Shape)
  67.                 procedure Initialize(x, y, xe, ye, color : word); override;
  68.                 function  Clone : shape; override;
  69.                 procedure Load( var f : file ); override;
  70.                 procedure Draw; override;
  71.                 procedure DrawHandles; override;
  72.                 procedure Select; override;
  73.                 procedure UnSelect; override;
  74.                 function  PtInRegion( px, py : word) : boolean; override;
  75.                 function  OnHandle( px, py : word; var ax, ay : word) : boolean; override;
  76.             end;
  77.  
  78.     GText =    object(Shape)
  79.                 data : string;
  80.                 procedure Initialize(x, y, xe, ye, color : word); override;
  81.                 function  Clone : shape; override;
  82.                 procedure Save( var f : file ); override;
  83.                 procedure Load( var f : file ); override;
  84.                 procedure SetText( s : string );
  85.                 procedure SetHeight( h : word );
  86.                 procedure Size( dx, dy : integer); override;
  87.                 procedure Draw;    override;
  88.                 procedure Erase; override;
  89.             end;
  90.  
  91.     Selector =    object(Shape)
  92.                     procedure Initialize(x, y, xe, ye, color : word); override;
  93.                     function  Clone : shape; override;
  94.                     procedure Load( var f : file ); override;
  95.                     procedure Draw; override;
  96.                 end;
  97.  
  98. implementation
  99.  
  100. uses MSGraph, Utility;
  101.  
  102. const
  103.     TypeFace = 'bt''tms rmn''';
  104.     CurrentHeight : word = 0;
  105.  
  106. var
  107.     CurrentFontInfo : _FontInfo;
  108.  
  109. { utilities }
  110.  
  111. function GSetFont( h : word) : boolean;
  112. var
  113.     fs : string[32];
  114.     nstr : string[5];
  115. begin
  116.     { see if trivial case }
  117.     if h=CurrentHeight then begin
  118.         GSetFont := TRUE;
  119.         exit;
  120.         end;
  121.  
  122.     { create net font selector }
  123.     fs := TypeFace;
  124.     str( h, nstr);
  125.     fs := fs + 'h' + nstr;
  126.  
  127.     { try to select font }
  128.     if    (_SetFont(fs)>0) and
  129.         (_GetFontInfo(CurrentFontInfo)<>-1) then begin
  130.         CurrentHeight := h;
  131.         GSetFont := TRUE;
  132.         end
  133.     else
  134.         GSetFont := FALSE;
  135. end;
  136.  
  137. procedure DrawHandle( x, y : word);
  138. const
  139.     HHEIGHT = 4;            { handle height }
  140.     HWIDTH  = 4;            { handle width  }
  141.     HHD2    = HHEIGHT div 2;
  142.     HWD2    = HWIDTH  div 2;
  143.  
  144.     {*
  145.     ** Image:  handle
  146.     ** Size:   24 bytes
  147.     ** Extent: 4,4
  148.     *}
  149.     handle : array[1..24] of byte = (
  150.                      5,0,5,0,240,240,240,240,240,240,240,240,240,240,
  151.                      240,240,240,240,240,240,0,0,0,0);
  152. begin
  153.     _PutImage( x-HWD2, y-HHD2, handle, _GXOR);
  154. end;
  155.  
  156. {
  157.     Returns TRUE if points are "near" each other
  158. }
  159. function Near( x1, y1, x2, y2 : word) : boolean;
  160. begin
  161.     Near :=    (abs(y2-y1) < HITPOINTTOLERANCE) and
  162.             (abs(x2-x1) < HITPOINTTOLERANCE);
  163. end;
  164.  
  165. procedure Shape.DrawHandles;
  166. begin
  167.     with self do begin
  168.         DrawHandle( x,         y);
  169.         DrawHandle( x+xe,    y);
  170.         DrawHandle( x,         y+ye);
  171.         DrawHandle( x+xe,     y+ye);
  172.         end;
  173. end;
  174.  
  175. procedure Shape.Error( s : string);
  176. begin
  177. {
  178.     writeln( s );
  179.     RunError(182);
  180. }
  181. end;
  182.  
  183. procedure Shape.Initialize( x, y, xe, ye, color : word);
  184. begin
  185.     self.typ := sShape;
  186.     self.x := x;
  187.     self.y := y;
  188.     self.xe := xe;
  189.     self.ye := ye;
  190.     self.color    := color;
  191.     self.selected := false;
  192. end;
  193.  
  194. function Shape.Clone : shape;
  195. var
  196.     s : Shape;
  197. begin
  198.     new(s);
  199.     with self do
  200.         s.Initialize( x, y, xe, ye, color);
  201.     Clone := s;
  202. end;
  203.  
  204. procedure Shape.Draw;
  205. begin
  206.     with self do begin
  207.         _SetColor(color);
  208.         _SetWriteMode( _GXOR );
  209.         _SetLineStyle($FFFF);
  210.         _Rectangle( _GBORDER, x, y, x+xe, y+ye);
  211.         if Selected then DrawHandles;
  212.         end;
  213. end;
  214.  
  215. procedure Shape.Erase;
  216. begin
  217.     self.Draw;
  218. end;
  219.  
  220. function Shape.PtInRegion( px, py : word) : boolean;
  221. var
  222.     xl, xh : word;
  223.     yl, yh : word;
  224.  
  225.  
  226. begin
  227.     with self do begin
  228.         xl := min( x, x+xe);
  229.         xh := max( x, x+xe);
  230.         yl := min( y, y+ye);
  231.         yh := max( y, y+ye);
  232.         PtInRegion :=    (px>=xl) and (px<=xh) and
  233.                         (py>=yl) and (py<=yh);
  234.         end;
  235. end;
  236.  
  237. procedure Shape.Select;
  238. begin
  239.     if not self.Selected then begin
  240.         self.DrawHandles;
  241.         self.Selected := TRUE;
  242.         end;
  243. end;
  244.  
  245. procedure Shape.UnSelect;
  246. begin
  247.     if self.Selected then begin
  248.         self.DrawHandles;
  249.         self.Selected := FALSE;
  250.         end;
  251. end;
  252.  
  253. function Shape.IsSelected : boolean;
  254. begin
  255.     IsSelected := self.Selected;
  256. end;
  257.  
  258. {
  259.     If on a handle, returns TRUE and sets ax and ay to the anchor point
  260. }
  261. function Shape.OnHandle( px, py : word; var ax, ay : word ) : boolean;
  262. begin
  263.     with self do
  264.         if not Selected then OnHandle := FALSE
  265.         else if Near( px, py, x, y) then begin
  266.             ax := x+xe;
  267.             ay := y+ye;
  268.             OnHandle := TRUE;
  269.             end
  270.         else if Near( px, py, x+xe, y+ye) then begin
  271.             ax := x;
  272.             ay := y;
  273.             OnHandle := TRUE;
  274.             end
  275.         else if Near( px, py, x+xe, y) then begin
  276.             ax := x;
  277.             ay := y+ye;
  278.             OnHandle := TRUE;
  279.             end
  280.         else if Near( px, py, x, y+ye) then begin
  281.             ax := x+xe;
  282.             ay := y;
  283.             OnHandle := TRUE;
  284.             end
  285.         else OnHandle := FALSE;
  286. end;
  287.  
  288. procedure Shape.Size( dx, dy : integer );
  289. begin
  290.     inc( self.xe, dx);
  291.     inc( self.ye, dy);
  292. end;
  293.  
  294. procedure Shape.Move( dx, dy : word );
  295. begin
  296.     inc( self.x, dx);
  297.     inc( self.y, dy);
  298. end;
  299.  
  300. (*
  301.                 typ      : ShapeTypes;
  302.                 x, y     : word;        { position }
  303.                 xe, ye   : integer;        { extent }
  304.                 color    : word;        { color }
  305.                 selected : boolean;     { state of selection }
  306. *)
  307. procedure Shape.Save( var f : file );
  308. var
  309.     written : word;
  310. begin
  311.     with self do begin
  312.         BlockWrite( f, typ,        sizeof(typ),    written);
  313.         BlockWrite( f, x,           sizeof(x),        written);
  314.         BlockWrite( f, y,          sizeof(y),        written);
  315.         BlockWrite( f, xe,        sizeof(xe),        written);
  316.         BlockWrite( f, ye,        sizeof(ye),        written);
  317.         BlockWrite( f, color,    sizeof(color),    written);
  318.         end;
  319. end;
  320.  
  321. { it is assume that the typ field has been read already }
  322. procedure Shape.Load( var f : file );
  323. var
  324.     numread : word;
  325. begin
  326.     with self do begin
  327.         typ := sShape;
  328.         BlockRead( f, x,           sizeof(x),        numread);
  329.         BlockRead( f, y,          sizeof(y),        numread);
  330.         BlockRead( f, xe,        sizeof(xe),        numread);
  331.         BlockRead( f, ye,        sizeof(ye),        numread);
  332.         BlockRead( f, color,    sizeof(color),    numread);
  333.         end;
  334. end;
  335.  
  336. procedure Rectangle.Initialize(x, y, xe, ye, color : word);
  337. begin
  338.     inherited self.Initialize(x, y, xe, ye, color );
  339.     self.typ := sRectangle;
  340. end;
  341.  
  342. function Rectangle.Clone : shape;
  343. var
  344.     s : Rectangle;
  345. begin
  346.     new(s);
  347.     with self do
  348.         s.Initialize( x, y, xe, ye, color);
  349.     Clone := s;
  350. end;
  351.  
  352. procedure Rectangle.Load( var f : file);
  353. begin
  354.     inherited self.Load( f );
  355.     with self do Initialize( x, y, xe, ye, color);
  356. end;
  357.  
  358. procedure FRectangle.Initialize(x, y, xe, ye, color : word);
  359. begin
  360.     inherited self.Initialize(x, y, xe, ye, color );
  361.     self.typ := sFRectangle;
  362. end;
  363.  
  364. function FRectangle.Clone : shape;
  365. var
  366.     s : FRectangle;
  367. begin
  368.     new(s);
  369.     with self do
  370.         s.Initialize( x, y, xe, ye, color);
  371.     Clone := s;
  372. end;
  373.  
  374. procedure FRectangle.Load( var f : file);
  375. begin
  376.     inherited self.Load( f );
  377.     with self do Initialize( x, y, xe, ye, color);
  378. end;
  379.  
  380. procedure FRectangle.Draw;
  381. begin
  382.     with self do begin
  383.         _SetColor(color);
  384.         _Rectangle( _GFILLINTERIOR, x, y, x+xe, y+ye);
  385.         if self.Selected then self.DrawHandles;
  386.         end;
  387. end;
  388.  
  389. procedure FRectangle.Erase;
  390. begin
  391.     with self do begin
  392.         if selected then self.DrawHandles;
  393.         _SetColor(0);
  394.         _Rectangle( _GFILLINTERIOR, x, y, x+xe, y+ye);
  395.         end;
  396. end;
  397.  
  398. procedure Ellipse.Initialize(x, y, xe, ye, color : word);
  399. begin
  400.     inherited self.Initialize(x, y, xe, ye, color );
  401.     self.typ := sEllipse;
  402. end;
  403.  
  404. function Ellipse.Clone : shape;
  405. var
  406.     s : Ellipse;
  407. begin
  408.     new(s);
  409.     with self do
  410.         s.Initialize( x, y, xe, ye, color);
  411.     Clone := s;
  412. end;
  413.  
  414. procedure Ellipse.Load( var f : file);
  415. begin
  416.     inherited self.Load( f );
  417.     with self do Initialize( x, y, xe, ye, color);
  418. end;
  419.  
  420. procedure Ellipse.Draw;
  421. begin
  422.     with self do begin
  423.         _SetColor(color);
  424.         _Ellipse( _GBORDER, x, y, x+xe, y+ye);
  425.         if self.Selected then self.DrawHandles;
  426.         end;
  427. end;
  428.  
  429. procedure Ellipse.Erase;
  430. begin
  431.     if self.Selected then self.DrawHandles;
  432.     _SetColor(0);
  433.     with self do _Ellipse( _GBORDER, x, y, x+xe, y+ye);
  434. end;
  435.  
  436. procedure FEllipse.Initialize(x, y, xe, ye, color : word);
  437. begin
  438.     inherited self.Initialize(x, y, xe, ye, color );
  439.     self.typ := sFEllipse;
  440. end;
  441.  
  442. function FEllipse.Clone : shape;
  443. var
  444.     s : FEllipse;
  445. begin
  446.     new(s);
  447.     with self do
  448.         s.Initialize( x, y, xe, ye, color);
  449.     Clone := s;
  450. end;
  451.  
  452. procedure FEllipse.Load( var f : file);
  453. begin
  454.     inherited self.Load( f );
  455.     with self do Initialize( x, y, xe, ye, color);
  456. end;
  457.  
  458. procedure FEllipse.Draw;
  459. begin
  460.     with self do begin
  461.         _SetColor(color);
  462.         _Ellipse( _GFILLINTERIOR, x, y, x+xe, y+ye);
  463.         if self.Selected then self.DrawHandles;
  464.         end;
  465. end;
  466.  
  467. procedure FEllipse.Erase;
  468. begin
  469.     with self do begin
  470.         if Selected then self.DrawHandles;
  471.         _SetColor(0);
  472.         _Ellipse( _GFILLINTERIOR, x, y, x+xe, y+ye);
  473.         end;
  474. end;
  475.  
  476. procedure Line.Initialize(x, y, xe, ye, color : word);
  477. begin
  478.     inherited self.Initialize(x, y, xe, ye, color );
  479.     self.typ := sLine;
  480. end;
  481.  
  482. function Line.Clone : shape;
  483. var
  484.     s : Line;
  485. begin
  486.     new(s);
  487.     with self do
  488.         s.Initialize( x, y, xe, ye, color);
  489.     Clone := s;
  490. end;
  491.  
  492. procedure Line.Load( var f : file);
  493. begin
  494.     inherited self.Load( f );
  495.     with self do Initialize( x, y, xe, ye, color);
  496. end;
  497.  
  498. procedure Line.Draw;
  499. begin
  500.     _SetWriteMode(_GXOR);
  501.     _SetLineStyle( $FFFF );
  502.     with self do begin
  503.         _SetColor(color);
  504.         _MoveTo(x, y);
  505.         _LineTo(x+xe, y+ye);
  506.         if self.Selected then self.DrawHandles;
  507.         end;
  508. end;
  509.  
  510. procedure Line.DrawHandles;
  511. begin
  512.     with self do begin
  513.         DrawHandle( x, y);
  514.         DrawHandle( x+xe, y+ye);
  515.         end;
  516. end;
  517.  
  518. procedure Line.Select;
  519. begin
  520.     if not self.Selected then begin
  521.         self.DrawHandles;
  522.         self.Selected := TRUE;
  523.         end;
  524. end;
  525.  
  526. procedure Line.UnSelect;
  527. begin
  528.     if self.Selected then begin
  529.         self.DrawHandles;
  530.         self.Selected := FALSE;
  531.         end;
  532. end;
  533.  
  534. function Line.PtInRegion(px, py : word) : boolean;
  535. var
  536.     Distance : longint;
  537.     xl, xh, yl, yh : word;
  538. begin
  539.     with self do begin
  540.         xl := min( x, x+xe);
  541.         xh := max( x, x+xe);
  542.         yl := min( y, y+ye);
  543.         yh := max( y, y+ye);
  544.         if     (px<xl) or (px>xh) or
  545.             (py<yl) or (py>yh) then PtInRegion := FALSE
  546.         else begin
  547.             Distance := abs(longint(ye)*(longint(x)-px) -
  548.                             longint(xe)*(longint(y)-py) );
  549.             PtInRegion := Distance < HITTOLERANCE;
  550.             end;
  551.         end;
  552. end;
  553.  
  554. {
  555.     If on a handle, returns TRUE and sets ax and ay to the anchor point
  556. }
  557. function Line.OnHandle( px, py : word; var ax, ay : word ) : boolean;
  558. begin
  559.     with self do
  560.         if not Selected then OnHandle := FALSE
  561.         else if Near( px, py, x, y) then begin
  562.             ax := x+xe;
  563.             ay := y+ye;
  564.             OnHandle := TRUE;
  565.             end
  566.         else if Near( px, py, x+xe, y+ye) then begin
  567.             ax := x;
  568.             ay := y;
  569.             OnHandle := TRUE;
  570.             end
  571.         else OnHandle := FALSE;
  572. end;
  573.  
  574. procedure GText.Initialize( x, y, xe, ye, color : word);
  575. begin
  576.     inherited self.Initialize(x, y, xe, ye, color);
  577.     self.typ := sGText;
  578.     self.data := '';
  579.  
  580.     if GSetFont(ye)
  581.         then self.ye :=CurrentFontInfo.PixHeight
  582.         else self.ye := 0;
  583.  
  584.     self.xe := 0;
  585. end;
  586.  
  587. function GText.Clone : shape;
  588. var
  589.     s : GText;
  590. begin
  591.     new(s);
  592.     with self do begin
  593.         s.Initialize( x, y, xe, ye, color);
  594.         s.SetText( data );
  595.         end;
  596.     Clone := s;
  597. end;
  598.  
  599. procedure GText.Save( var f : file );
  600. var
  601.     written : word;
  602.     l : byte;
  603. begin
  604.     with self do begin
  605.         inherited Save(f);
  606.         l := length(data);
  607.         BlockWrite( f, l, sizeof(l), written);
  608.         BlockWrite( f, pointer(@data[1])^, l, written);
  609.         end;
  610. end;
  611.  
  612. procedure GText.Load( var f : file);
  613. var
  614.     numread : word;
  615.     l : byte;
  616.     d : string;
  617. begin
  618.     inherited self.Load( f );
  619.     BlockRead( f, l, sizeof(l), numread);
  620.     d[0] := chr(l);
  621.     BlockRead( f, pointer(@d[1])^, l, numread);
  622.     with self do begin
  623.         Initialize( x, y, xe, ye, color);
  624.         SetText( d );
  625.         end;
  626. end;
  627.  
  628. procedure GText.SetText( s : string);
  629. begin
  630.     self.data := s;
  631.     self.xe := _GetGTextExtent(s);
  632. end;
  633.  
  634. procedure GText.SetHeight( h : word );
  635. begin
  636.     if GSetFont( h ) then begin
  637.         self.ye := CurrentFontInfo.PixHeight;
  638.         self.xe := _GetGTextExtent( self.data );
  639.         end;
  640. end;
  641.  
  642. procedure GText.Size( dx, dy : integer); override;
  643. begin
  644.     self.SetHeight( self.ye+dy );
  645. end;
  646.  
  647. procedure GText.Draw;
  648. begin
  649.     with self do begin
  650.         _MoveTo( x, y);
  651.         if not GSetFont(ye) then self.Error('Unable to set font');
  652.         _SetColor( color );
  653.         _OutGText( data );
  654.         if Selected then self.DrawHandles;
  655.         end;
  656. end;
  657.  
  658. procedure GText.Erase;
  659. begin
  660.     with self do begin
  661.         if Selected then self.DrawHandles;
  662.         _SetColor(0);
  663.         _Ellipse( _GFILLINTERIOR, x, y, x+xe, y+ye);
  664.         end;
  665. end;
  666.  
  667. procedure Selector.Initialize(x, y, xe, ye, color : word);
  668. begin
  669.     inherited self.Initialize(x, y, xe, ye, color );
  670.     self.typ := sSelector;
  671. end;
  672.  
  673. function Selector.Clone : shape;
  674. var
  675.     s : Selector;
  676. begin
  677.     new(s);
  678.     with self do
  679.         s.Initialize( x, y, xe, ye, color);
  680.     Clone := s;
  681. end;
  682.  
  683. procedure Selector.Load( var f : file);
  684. begin
  685.     inherited self.Load( f );
  686.     with self do Initialize( x, y, xe, ye, color);
  687. end;
  688.  
  689. procedure Selector.Draw;
  690. var
  691.     ax, ay : word;
  692. begin
  693.     with self do begin
  694.         ax := xe div 4;
  695.         ay := ye div 4;
  696.         _SetColor(color);
  697.         _SetWriteMode( _GXOR );
  698.         _MoveTo( x+ax, y+ye-ay);
  699.         _LineTo( x+xe-ax, y+ay);
  700.         _MoveTo( x+xe-(ax+ax), y+ay);
  701.         _LineTo( x+xe-ax, y+ay);
  702.         _LineTo( x+xe-ax, y+ay+ay);
  703.         if Selected then self.DrawHandles;
  704.         end;
  705. end;
  706.  
  707. begin
  708. end.
  709.